package cn.clq.ymcc.mq.consumer;

import cn.clq.ymcc.constant.PayOrderStateConstants;
import cn.clq.ymcc.domain.PayOrder;
import cn.clq.ymcc.dto.PayDto;
import cn.clq.ymcc.service.IPayOrderService;
import cn.clq.ymcc.util.AssertUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * @author clqlongbao
 * @version 1.0
 * @description: 根据课程订单生成支付单
 * @date 2022/8/1 11:05
 */
@Component
@RocketMQMessageListener(
        consumerGroup="course-order-pay-consumer",
        topic="course-order-topic",
        selectorExpression="course-order-tag"
)
@Slf4j
public class CourseOrder2PayOrderConsumer implements RocketMQListener<MessageExt> {

    @Autowired
    private IPayOrderService payOrderService;

    //消费者消费消息，必须保持幂等性
    @Override
    public void onMessage(MessageExt message) {
        System.out.println("我进入了消费者");
        //1.消息体空校验
        byte[] body = message.getBody();
        AssertUtil.isNotNull(body,"消费者接收的消息体不能为空");
        //2.将消息体反序列化
        //byte[]-->JsonString-->PayDto
        String jsonStr = new String(body, StandardCharsets.UTF_8);
        PayDto payDto = JSONObject.parseObject(jsonStr, PayDto.class);
        //3.根据订单号查询支付单是否已经存在
        //扩展：作为RocketMq，消费方是否签收消息是通过是否有异常来判断的
        //在onMessage方法体中：
        //  1.如果有异常，签收失败 -- 此消息会滞留在Mq中，下次还会再被消费--直到MQ 自动清理垃圾
        //  2.如果没有异常，签收成功  -- 消息就不再会被再次消费
        PayOrder payOrder = payOrderService.selectByOrderNo(payDto.getOrderNo());
        if(payOrder != null){
            //3.1说明已经消费过，直接签收消息--后面Mq就不会在推送此消息了
            log.info("支付单已经存在了，直接签收消息，不再重复消费");
            return;
        }
        //3.2说明是第一次来消费这个消息，保存支付单payOrder
        payOrder = new PayOrder();
        BeanUtils.copyProperties(payDto,payOrder);
        payOrder.setCreateTime(new Date());
        payOrder.setPayStatus(PayOrderStateConstants.STATE_WAIT_PAY);
        payOrderService.insert(payOrder);
        System.out.println("支付单保存成功");
    }
}
